package com.wms.controller;


import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestControllerAdvice
public class RequestExceptionHandler {

    /**
     * 默认参数错误状态码
     */
    private final static int CODE_400 = 400;
    /**
     * 默认参数错误提示信息
     */
    private final static String ERROR_MSG_400 = "参数错误";


    /**
     * 使用@Valid/@Validated对@RequestBody对象校验失败后抛出的异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Map<String, Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        Optional<ObjectError> optional = bindingResult.getAllErrors().stream().findFirst();

        Map<String, Object> result = new HashMap<>(2);
        result.put("code", CODE_400);
        result.put("message", optional.isPresent() ? optional.get().getDefaultMessage() : ERROR_MSG_400);
        return result;
    }

    /**
     * 在@RequestParam上validate失败后抛出的异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Map<String, Object> handleConstraintViolationException(ConstraintViolationException e) {
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        Optional<ConstraintViolation<?>> optional = violations.stream().findFirst();

        Map<String, Object> result = new HashMap<>(2);
        result.put("code", CODE_400);
        result.put("message", optional.isPresent() ? optional.get().getMessage() : ERROR_MSG_400);
        return result;
    }

    /**
     * 使用@Valid/@Validated对实体对象校验失败后抛出的异常
     */
    @ExceptionHandler(BindException.class)
    public Map<String, Object> handleBindException(BindException e) {
        BindingResult bindingResult = e.getBindingResult();
        Optional<ObjectError> optional = bindingResult.getAllErrors().stream().findFirst();

        Map<String, Object> result = new HashMap<>(2);
        result.put("code", CODE_400);
        result.put("message", optional.isPresent() ? optional.get().getDefaultMessage() : ERROR_MSG_400);
        return result;
    }

    /**
     * 使用@RequestParam，缺少参数抛出的异常
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Map<String, Object> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        Map<String, Object> result = new HashMap<>(2);
        result.put("code", CODE_400);
        result.put("message", e.getMessage());
        return result;
    }

}
